package com.remote.server.handle;

import com.remote.common.RemoteFactory;
import com.remote.common.command.Commands;
import com.remote.common.exception.RemoteException;
import com.remote.common.exception.TaskExecutorException;
import com.remote.common.model.Request;
import com.remote.common.model.ServerClientInfo;
import com.remote.common.util.TaskExecutors;
import com.remote.common.util.Utils;
import io.netty.channel.ChannelHandlerContext;

import static com.remote.common.constant.MessageConstants.*;

/**
 * 控制命令处理
 */
public class ControlHandle extends BaseServerHandler {


    public ControlHandle(RemoteFactory remoteFactory) {
        super(remoteFactory);
    }

    @Override
    protected void handleO(ChannelHandlerContext ctx, Request request) {
        try {
            Boolean result = notifyPuppetConnect(ctx, request);
            if (result == null || !result) {
                info(request, CONNECT_PUPPET_FAILED);
                Utils.sendError(ctx.channel(), request, CONNECT_PUPPET_FAILED);
                return;
            }
            final ServerClientInfo control = this.getRemoteFactory().getClient(request.getClientId());
            final ServerClientInfo puppet = this.getRemoteFactory().getClient(request.getTargetClientId());

            if (control == null || !control.getContext().channel().isOpen()
                    || puppet == null || !puppet.getContext().channel().isOpen()) {
                info(request, CONNECT_PUPPET_FAILED, CONNECTION_EXIST);
                Utils.sendError(ctx.channel(), request, CONNECT_PUPPET_FAILED);
            } else {
                info(request, CONNECT_SUCCESSFULLY);
                puppet.putControl(control.getClientInfo(), control.getContext());
                control.putPuppet(puppet.getClientInfo(), puppet.getContext());
                //通知傀儡
                puppet.getContext().writeAndFlush(Utils.buildResponse(request, Commands.CONTROL, null));
                //给控制端返回消息，通知其做好准备
                control.getContext().writeAndFlush(Utils.buildResponse(request, Commands.CONTROL, puppet.getClientInfo()));
            }
        } catch (RemoteException e) {
            error(CONNECT_PUPPET_FAILED, e.getMessage());
        } catch (TaskExecutorException e) {
            error(CONNECT_PUPPET_FAILED, e.getMessage());
        }
    }


    private Boolean notifyPuppetConnect(ChannelHandlerContext ctx, Request inbound) throws RemoteException, TaskExecutorException {

        return TaskExecutors.submit(() -> {
            final ServerClientInfo control = this.getRemoteFactory().getClient(inbound.getClientId());
            if (control == null || ctx != control.getContext() || !control.getContext().channel().isOpen()) {
                return false;
            }
            final ServerClientInfo puppet = this.getRemoteFactory().getClient(inbound.getTargetClientId());
            if (puppet != null && puppet.getContext().channel().isOpen()) {
                return true;
            }
            //2.返回null时，会重试
            return null;
        }, 1000, 10);
    }
}
